package com.yth.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

import java.io.StringWriter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Velocity模板工具类
 *
 * @author yutianhong
 * @version 1.0
 * @since 2024/11/20 17:14
 */
public class VelocityTemplateUtils {

    private static VelocityEngine velocityEngine = null;

    // 定义正则表达式模式以匹配Velocity变量
    // 这里使用 \\$\\{(\\w+)\\} 以捕获 ${variableName} 形式的变量
    private static final Pattern PATTERN = Pattern.compile("(?<!\\\\)(?:\\\\\\\\)*\\$\\{([^}]+)\\}");

    /**
     * 使用Velocity将输入文本中的变量替换为Map中的值
     *
     * @param templateStr 模板字符串，包含Velocity变量
     * @param contextMap  上下文Map，用于提供模板中变量的值
     * @return 替换变量后的字符串
     */
    public static String renderTemplate(String templateStr, Map<String, Object> contextMap) {
        if (StringUtils.isBlank(templateStr)) {
            return templateStr;
        }

        initializeVelocityEngineIfNecessary();
        if (contextMap == null) {
            contextMap = Collections.emptyMap();
        }
        // 创建上下文，并将变量放入上下文中
        VelocityContext velocityContext = new VelocityContext();
        for (Map.Entry<String, Object> entry : contextMap.entrySet()) {
            velocityContext.put(entry.getKey(), entry.getValue());
        }

        // 输出
        StringWriter stringWriter = new StringWriter();
        velocityEngine.evaluate(velocityContext, stringWriter, VelocityTemplateUtils.class.getSimpleName(), templateStr);

        return stringWriter.toString();
    }

    /**
     * 从Velocity模板字符串中提取所有变量
     *
     * @param templateStr 包含Velocity变量的模板字符串
     * @return 变量名的集合
     */
    public static Set<String> extractVariables(String templateStr) {
        Matcher matcher = PATTERN.matcher(templateStr);

        Set<String> variables = new HashSet<>();
        while (matcher.find()) {
            variables.add(matcher.group(1));
        }
        return variables;
    }

    private static void initializeVelocityEngineIfNecessary() {
        if (velocityEngine != null) {
            return;
        }
        synchronized (VelocityTemplateUtils.class) {
            if (velocityEngine == null) {
                // 初始化Velocity引擎
                Properties props = new Properties();
                props.setProperty("runtime.references.strict", "true"); // 选项，严格模式，变量未定义时报错
                VelocityEngine ve = new VelocityEngine(props);
                ve.init();
                VelocityTemplateUtils.velocityEngine = ve;
            }
        }
    }

    private VelocityTemplateUtils() {
    }

}
